package com.huangyi.chatservice.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.huangyi.chatservice.domain.dto.MessageDTO;
import com.huangyi.chatservice.domain.dto.SessionStatusDetailDTO;
import com.huangyi.commoncore.utils.JsonUtil;
import com.huangyi.commonredis.service.RedisService;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

@Component
@Slf4j
public class ChatCacheService {

    @Autowired
    private RedisService redisService;

    /**
     * 用户id - 会话ids
     */
    private static final String CHAT_ZSET_USER_PREFIX = "chat:zset:user:";

    /**
     * 会话id - 会话详情DTO
     */
    private static final String CHAT_SESSION_PREFIX = "chat:session:";

    /**
     * 会话 id - 聊天消息列表
     */
    private static final String CHAT_ZSET_SESSION_PREFIX = "chat:zset:session:";


    /**
     * 新增用户下的新会话
     * @param userId 用户id
     * @param sessionId 会话id
     * @param lastSessionTime 会话创建时间, 排序规则
     */
    public void addUserSessionToCache(Long userId, Long sessionId, Long lastSessionTime) {
        try{
            String key = CHAT_ZSET_USER_PREFIX + userId;
            redisService.addMemberZSet(key, sessionId, lastSessionTime);
        }catch(Exception e){
            log.error("新增用户下的新会话id缓存时发生异常, userId:{}",userId,e);
        }
    }

    /**
     * 获取用户下的会话列表
     *
     * @param userId
     * @return
     */
    public Set<Long> getUserSessionsByCache(Long userId) {
        Set<Long> sessionIds = new HashSet<>();
        try {
            String key = CHAT_ZSET_USER_PREFIX + userId;
            sessionIds = redisService.getCacheZSetDesc(
                    key, new TypeReference<LinkedHashSet<Long>>() {});
            if (CollectionUtils.isEmpty(sessionIds)) {
                return new HashSet<>();
            }
        } catch (Exception e) {
            log.error("从缓存中获取用户下的会话列表异常，userId:{}", userId, e);
        }
        return sessionIds;
    }

    /**
     * 缓存会话详情信息
     * @param sessionId 会话id
     * @param sessionDTO 会话详情信息
     */
    public void cacheSessionDTO(Long sessionId, SessionStatusDetailDTO sessionDTO) {
        try{
            String key = CHAT_SESSION_PREFIX + sessionId;
            redisService.setCacheObject(key, JsonUtil.obj2String(sessionDTO));
        }catch (Exception e){
            log.error("缓存会话详情信息时发生异常, sessionId:{}", sessionId, e);
        }
    }

    /**
     * 获取会话详情信息缓存
     * @param sessionId 要取得会话id详情缓存
     * @return 会话id详情缓存
     */
    public SessionStatusDetailDTO getSessionDTOByCache(Long sessionId) {
        SessionStatusDetailDTO sessionDTO = null;
        try{
            String key = CHAT_SESSION_PREFIX + sessionId;
            String str = redisService.getCacheObject(key,String.class);
            if(StringUtils.isBlank(str)){
                return null;
            }
            sessionDTO = JsonUtil.string2Obj(str,SessionStatusDetailDTO.class);
        }catch (Exception e){
            log.error("获取会话详情信息缓存发生异常, sessionId:{}", sessionId, e);
        }

        return sessionDTO;
    }

    /**
     * 新增会话下的消息缓存
     *
     * @param sessionId
     * @param messageDTO
     */
    public void addMessageDTOToCache(Long sessionId, MessageDTO messageDTO) {
        try{
            String key = CHAT_ZSET_SESSION_PREFIX + sessionId;
            // 增不涉及会话集合参数, 可以在内部设置 redis 会话集合
            redisService.addMemberZSet(key, messageDTO, Long.parseLong(messageDTO.getMessageId()));
        }catch (Exception e){
            log.error("新增会话下的消息缓存发生异常，sessionId:{}", sessionId, e);
        }
    }

    /**
     * 获取会话下的聊天记录集合
     *
     * @param sessionId
     * @return
     */
    public Set<MessageDTO> getMessageDTOsByCache(Long sessionId) {
        Set<MessageDTO> messageDTOs = null;
        try{
            String key = CHAT_ZSET_SESSION_PREFIX + sessionId;
            messageDTOs = redisService.getCacheZSetDesc(key, new TypeReference<LinkedHashSet<MessageDTO>>() {});
            if(CollectionUtils.isEmpty(messageDTOs)){
                return new HashSet<>();
            }
        }catch (Exception e){
            log.error("获取会话下的消息缓存发生异常，sessionId:{}", sessionId, e);
        }

        return messageDTOs;
    }

    /**
     * 删除会话下的聊天记录集合中指定的消息
     *
     * @param sessionId
     * @return
     */
    public void removeMessageDTOFromCache(Long sessionId, String messageId) {
        try{
            String key = CHAT_ZSET_SESSION_PREFIX + sessionId;
            redisService.removeZSetByScore(key,
                    Long.parseLong(messageId), Long.parseLong(messageId));
        }catch (Exception e){
            log.error("删除会话下的指定消息缓存发生异常，sessionId:{}, messageId:{}", sessionId, messageId, e);
        }
    }

}
